package com.example.testlib

import java.lang.reflect.InvocationHandler
import java.lang.reflect.Method
import com.example.testlib.agencymode.HouseAgentSmartKT
import com.example.testlib.agencymode.HouseOwnerKT

// 只有当 isDebug 为 true，才会执行后面的 block 函数
fun Onlyif(isDebug: Boolean, block: () -> Unit) {
    if (isDebug) block()
}

fun main() {
    println("Hello Kotlin World!")
    Test.say("Good Morning~")

    // 扩展函数用法
//    Dog().printName(Dog())

    // lambda 闭包
    print("hello")

    val runnable = Runnable {
        print("Runnable run!")
    }
    val function: () -> Unit
    function = runnable::run
    Onlyif(true, function)


    Zoo(Dog()).bark()


    HouseAgent(HouseOwner()).visitHouse()
    HouseAgent(HouseOwner()).argueRent(500)
    HouseAgent(HouseOwner()).signAgreement()


    // 测试 isEnSent 方法
    val str = "我"
    println(str.isEnSent())


    val smartAgent = HouseAgentSmartKT(HouseOwnerKT()).mHouseOwner
    smartAgent?.visitHouse()
    smartAgent?.argueRent(500)
    smartAgent?.signAgreement()


    // Kotlin 数据类
    val book = Book(1, "鲁迅文集")
    book.id = 23    // setter 方法
    val(bookId, bookName) = book
    print("bookName = $bookName")

    val car = Car("蔚来", 200000.0)
    val (brand, price) = car
    val person = mapOf<String, String>("name" to "Jack", "age" to "23")
    for ((key, value) in person) {
        println("key: $key ==== value: $value")
    }


    // Kotlin 循环写法
//    for (i in 1..10) {
//        print("$i ")
//    }
//    print("=========")
//    for (i in 1 until 10) {
//        print("$i ")
//    }
//    print("=========")
//    for (i in 10 downTo 1) {
//        print("$i ")
//    }
//    print("=========")
//    for (i in 1..10 step 2) {
//        print("$i ")
//    }
//    print("=========")
//    repeat(10) {
//        print(it)
//    }
    val list = listOf("I", "am", "Chinese")
    for (str in list) {
        print("$str ")
    }
    for ((index, str) in list.withIndex()) {
        print("第${index}元素是$str")
    }


    // Kotlin 集合
    CollectionExample.a()


    // Kotlin 集合操作符
//    val list1 = arrayListOf<Char>('a', 'n', 'z', 'k')
//    val t = list1.map { it - 'b' }.filter { it > 0 }.find { it > 2 }
//    print("The final answer is $t")
//    CollectionOperator.exampleOutput()
//    CollectionOperator.convertTest()
//    CollectionOperator.commonOperatorExample()
//    CollectionOperator.convertTest()


//    ScopeFunctionExample.funcExample()

//    SmallTips.`123`()
//    SmallTips.` `()
//    SmallTips.`  `()

//    EqualsExample.func1()

    val p = Person()
    println("p.age = ${p.age}  p.name = ${p.name}")
    p.age = 20
    println("p.age = ${p.age}  p.name = ${p.name}")
    p.age = 5
    println("p.height = ${p.height}")

}


object Test {
    fun say(msg: String) {
        println(msg)
    }
}


// lambda 闭包
val print = {name: String ->
    println(name)
}


// 扩展函数用法
//open class Animal
//class Dog: Animal()
//
//fun Animal.getName() = "animal"
//fun Dog.getName() = "dog"
//
//fun Animal.printName(animal: Animal) {
//    println(animal.getName())
//}


// Kotlin 动态代理
interface Animal {
    fun bark()
}

class Dog: Animal {
    override fun bark() {
        println("Wang")
    }
}
// 通过传递的 animal 对象作为代理 来代理后面的 animal 对象执行
class Zoo(animal: Animal): Animal by animal {
    override fun bark() {
        println("Zoo")    // 也可以重写里面的 bark 方法，所以就不会执行它代理的 Animal 对象的 bark 方法了
    }
}
// Kotlin 会将动态代理在编译之后转为静态代理去调用，所以 kotlin 的动态代理比 java 的动态代理效率高，因为 java 的
// 动态代理是由反射实现的，反射的效率相比之前是比较低的


interface IRentHouse {
    // 带领租客看房
    fun visitHouse()

    // 讨价还价
    fun argueRent(rent: Int)

    // 签合同
    fun signAgreement()
}

class HouseOwner: IRentHouse {
    override fun visitHouse() {
        println("带领看房，介绍房屋特点")
    }

    override fun argueRent(rent: Int) {
        println("提出租金为：$rent")
    }

    override fun signAgreement() {
        println("签合同")
    }
}

class HouseAgent(houseOwner: IRentHouse): IRentHouse by houseOwner {
    var mTip = 0
    private val mHouseOwner = houseOwner

    fun giveTip(tip: Int){
        mTip = tip
    }

    override fun visitHouse() {
        if (mTip > 10) {
            mHouseOwner.visitHouse()
        } else {
            println("小费不够，暂不能看房")
        }
    }
}

class Car(var brand: String, var price: Double) {
    operator fun component1(): String {
        return this.brand
    }
    operator fun component2(): Double {
        return this.price
    }
}

